#pragma once

#include "logmessage.hpp"
#include <string>
#include <cstdio>
#include <cerrno>
#include <cstring>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

class UdpClient
{
    int _sockfd;
    std::string _serverip;
    uint16_t _serverport;

public:
    UdpClient(const std::string &ip, const uint16_t port)
        : _serverip(ip),
          _serverport(port),
          _sockfd(-1)
    {
    }

    void InitClient()
    {
        // 1.创建套接字文件描述符
        _sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (_sockfd == -1)
        {
            LogMessage(FATAL, "(%d)%s", errno, strerror(errno));
            exit(errno);
        }
        // 2.不需要显示绑定IP和端口号，OS会自动绑定
        LogMessage(DEBUG, "init client success!");
    }

    void Run()
    {
        char buffer[1024];
        sockaddr_in server;
        memset(&server, 0, sizeof(server));
        server.sin_family = AF_INET;
        server.sin_port = htons(_serverport);
        server.sin_addr.s_addr = inet_addr(_serverip.c_str());

        while (true)
        {
            printf("Please Enter$ ");
            fgets(buffer, sizeof(buffer), stdin);
            buffer[strlen(buffer) - 1] = '\0'; // 删除换行符
            if (strcmp(buffer, "quit") == 0)
            {
                break;
            }
            // 当client首次给server发送数据时，OS会自动给client绑定IP地址和端口号
            ssize_t s = sendto(_sockfd, buffer, strlen(buffer), 0, (sockaddr *)&server, sizeof(server));
            if (s == -1)
            {
                LogMessage(ERROR, "(%d)%s", errno, strerror(errno));
                continue;
            }
        }
    }

    ~UdpClient()
    {
        if (_sockfd >= 0)
            close(_sockfd);
    }
};
